﻿using System;
using System.Collections.Generic;

namespace Engine.Rule
{
    public abstract class AttributeType
    {
        public AttributeType(string name, string description)
        {
            this.name = name;
            this.description = description;
        }

        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private string description;
        public string Description
        {
            get { return description; }
            set { description = value; }
        }
    }

    public abstract class Attribute<T_TYPE>
        where T_TYPE : AttributeType
    {
        public Attribute(T_TYPE type, int value)
        {
            this.type = type;
        }

        private T_TYPE type;
        public T_TYPE Type
        {
            get { return type; }
        }

        private int value;
        public int Value
        {
            get { return this.value; }
            set { this.value = value; }
        }
    }

    public abstract class AttributeTypeGroup<T_TYPE>
        where T_TYPE : AttributeType
    {
        private T_TYPE[] types;
        public T_TYPE[] Types
        {
            get { return types; }
            set { types = value; }
        }

        protected AttributeTypeGroup(T_TYPE[] Types)
        {
            this.types = Types;
        }
    }

    public abstract class AttributeGroup<T_TYPE, T, T_TYPE_GROUP>
        where T_TYPE : AttributeType
        where T : Attribute<T_TYPE>
        where T_TYPE_GROUP : AttributeTypeGroup<T_TYPE>
    {
        protected T[] attributes;

        public abstract int LimitMin
        {
            get;
        }

        public abstract int LimitMax
        {
            get;
        }

        protected abstract T createAttribute(T_TYPE type, int value);

        public AttributeGroup(T_TYPE_GROUP group)
        {
            attributes = new T[group.Types.Length];
            for (int tIndex = 0; tIndex < group.Types.Length; tIndex++)
            {
                attributes[tIndex] = createAttribute(group.Types[tIndex], 0);
            }
        }

        public void SetValue(T_TYPE type, int value)
        {
            for (int aIndex = 0; aIndex < attributes.Length; aIndex++)
            {
                if (attributes[aIndex].Type.Equals(type))
                {
                    if (value < LimitMin)
                    {
                        attributes[aIndex].Value = LimitMin;
                    }
                    else if (value > LimitMax)
                    {
                        attributes[aIndex].Value = LimitMax;
                    }
                    else
                    {
                        attributes[aIndex].Value = value;
                    }
                    break;
                }
            }
        }

        public void IncreaseValue(T_TYPE type)
        {
            for (int aIndex = 0; aIndex < attributes.Length; aIndex++)
            {
                if (attributes[aIndex].Type.Equals(type))
                {
                    int value = attributes[aIndex].Value + 1;
                    if (value < LimitMin)
                    {
                        attributes[aIndex].Value = LimitMin;
                    }
                    else if (value > LimitMax)
                    {
                        attributes[aIndex].Value = LimitMax;
                    }
                    else
                    {
                        attributes[aIndex].Value = value;
                    }
                    break;
                }
            }
        }

        public void DecreaseValue(T_TYPE attribute)
        {
            for (int aIndex = 0; aIndex < attributes.Length; aIndex++)
            {
                if (attributes[aIndex].Type.Equals(attribute))
                {
                    int value = attributes[aIndex].Value - 1;
                    if (value < LimitMin)
                    {
                        attributes[aIndex].Value = LimitMin;
                    }
                    else if (value > LimitMax)
                    {
                        attributes[aIndex].Value = LimitMax;
                    }
                    else
                    {
                        attributes[aIndex].Value = value;
                    }
                    break;
                }
            }
        }

        public int GetValue(T_TYPE attribute)
        {
            for (int aIndex = 0; aIndex < attributes.Length; aIndex++)
            {
                if (attributes[aIndex].Type.Equals(attribute))
                {
                    return attributes[aIndex].Value;
                }
            }
            return -1;
        }
    }
}
